;************************************************
; Floppy drive interface routines (floppy.inc)
; Reindeer OS
;************************************************

bits 16

;*************************************************;
;	OEM Parameter block
;*************************************************;

bpbOEM					db "Reindeer"	
bpbBytesPerSector:  	DW 512
bpbSectorsPerCluster: 	DB 1
bpbReservedSectors: 	DW 1
bpbNumberOfFATs: 	    DB 2
bpbRootEntries: 	    DW 224
bpbTotalSectors: 	    DW 2880
bpbMedia: 	            DB 0xF0
bpbSectorsPerFAT: 	    DW 9
bpbSectorsPerTrack: 	DW 18
bpbHeadsPerCylinder: 	DW 2
bpbHiddenSectors: 	    DD 0
bpbTotalSectorsBig:     DD 0
bsDriveNumber: 	        DB 0
bsUnused: 	            DB 0
bsExtBootSignature: 	DB 0x29
bsSerialNumber:	        DD 0xa0a1a2a3
bsVolumeLabel: 	        DB "MOS FLOPPY "
bsFileSystem: 	        DB "FAT12   "

sector					DB	0x00
head					DB	0x00
track					DB	0x00

datasector				dw	0x0000
cluster					dw	0x0000

;*****************************
; Covert CHS to LBA
; LBA = (cluster - 2) * sectors per cluster
;*****************************

clusterToLba:
	sub		ax, 0x0002				; zero base cluster number
	xor		cx, cx
	mov		cl, BYTE [bpbSectorsPerCluster]
	mul		cx
	add		ax, WORD [datasector]
	ret

;*****************************
; Covert LBA to CHS function
; AX - LBA address to convert
; sector = (logical sector / sectors per track) + 1
; head = (logical sector / sectors per track) MOD number of heads
; track = logical sector / (sectors per track * number of heads)
;*****************************

lbaToChs:
	xor		dx, dx						; prepare dx:ax for operation
	div		WORD [bpbSectorsPerTrack]	;calculate
	inc		dl							;adjust for sector 0
	mov		BYTE [sector], dl
	xor		dx, dx
	div		WORD [bpbHeadsPerCylinder]
	mov		BYTE [head], dl
	mov		BYTE [track], al
	ret

;*************************
; Read Sector Function
; CX - number of sectors to read
; AX - starting sector
; ES:BX - buffer to read for
;*************************

readSectors:
	.MAIN:
		mov		di, 0x0005		; five retries for error
	.SECTORLOOP:
		push	ax
		push	bx
		push	cx
		call	lbaToChs
		mov		ah, 0x02					; function 02 of int 0x13
		mov		al, 0x01					; read 1 sector
		mov		dl, [bsDriveNumber]			; drive 0
		mov		ch, BYTE [track]			; cylinder number
		mov		cl, BYTE [sector]			; sector to read (The second sector)
		mov		dh, BYTE [head]				; head number
		int		0x13
		jnc		.OK
		xor		ax, ax						; function 01, reset disk
		int		0x13						; invoke bios
		dec		di							; decrement error counter
		pop		cx
		pop		bx
		pop		ax
		jnz		.SECTORLOOP
		int		0x18
	.OK:
		pop		cx
		pop		bx
		pop		ax
		add		bx, WORD[bpbBytesPerSector]
		inc		ax
		mov		si, msgProgress
		call	Puts16
		loop	.MAIN
		ret